<template>
  <div>
    <div class="flex justify-between pt-2 items-center">
      <div>
        <Checkbox
          v-model:checked="checkAll"
          :indeterminate="indeterminate"
          @change="onCheckAllChange"
        >
          全选
        </Checkbox>
      </div>
      <div>
        <redo-outlined class="cursor-pointer" @click="handleClickKey" title="刷新" />
      </div>
    </div>
    <Divider style="margin: 10px; width: 100%" />
    <Scrollbar>
      <div style="width: 300px">
        <Tree
          v-model:checked-keys="selectChecked"
          checkable
          v-model:expandedKeys="expandedKeys"
          :tree-data="plainOptions"
          :checkStrictly="true"
          :field-names="{ title: 'name', key: 'code' }"
          @check="handleChange"
        />
      </div>
    </Scrollbar>
  </div>
</template>
<script lang="ts">
  import { defineComponent, reactive, toRefs, watch, ref, nextTick } from 'vue';
  import { Checkbox, Divider, Tree } from 'ant-design-vue';
  import { RedoOutlined } from '@ant-design/icons-vue';
  import { Scrollbar } from '/@/components/Scrollbar';
  export default defineComponent({
    components: { Checkbox, Divider, RedoOutlined, Tree, Scrollbar },
    props: {
      list: {
        type: Array,
        defalut: () => [],
      },
      modelValue: {
        type: String,
        defalut: '',
      },
    },
    emits: ['change', 'handleClickKey', 'update:modelValue'],
    setup(props, { emit }) {
      const plainOptions = ref<any[]>([]);
      const selectChecked = ref<{ checked: string[]; halfChecked: string[] }>({
        checked: [],
        halfChecked: [],
      });
      const state = reactive({
        indeterminate: false,
        checkAll: false,
      });
      const treeData = ref([]);
      const treeDataKeys = ref<string[]>([]);
      const expandedKeys = ref<string[]>([]);
      const checkedList = ref<string[]>([]);

      const onCheckAllChange = (e: any) => {
        Object.assign(state, {
          indeterminate: false,
        });
        checkedList.value = e.target.checked ? treeDataKeys.value : [];
        selectChecked.value['checked'] = checkedList.value;
      };
      watch(
        () => checkedList.value,
        (val) => {
          state.indeterminate = !!val.length && val.length < treeDataKeys.value.length;
          state.checkAll =
            val.length === treeDataKeys.value.length && treeDataKeys.value.length != 0;

          emit('update:modelValue', val.join(','));
          emit('change', val);
        },
      );

      watch(
        () => props.list,
        async (val) => {
          await nextTick();
          if (val && val.length) {
            plainOptions.value = val;
            const codes: string[] = plainOptions.value.map((item) => item.code);
            checkedList.value = codes;
            expandedKeys.value = codes;
            selectChecked.value['checked'] = codes;
            treeDataKeys.value = [];
            treeData.value = setChildren(val);
          } else {
            plainOptions.value = [];
          }
        },
        {
          immediate: true,
        },
      );
      const setChildren = (data) => {
        data.forEach((item) => {
          item.title = item.name;
          item.key = item.code;
          treeDataKeys.value.push(item.code);
          if (item.children && item.children.length) {
            setChildren(item.children);
          }
        });
        return data;
      };

      const handleChange = (e) => {
        selectChecked.value = e;
        checkedList.value = e['checked'];
        setTimeout(() => {
          emit('change', checkedList.value);
        });
      };
      const getCheckedList = async () => {
        await nextTick();
        return checkedList.value;
      };
      const handleClickKey = () => {
        emit('handleClickKey');
      };

      return {
        ...toRefs(state),
        plainOptions,
        onCheckAllChange,
        handleChange,
        getCheckedList,
        handleClickKey,
        selectChecked,
        expandedKeys,
        checkedList,
      };
    },
  });
</script>
<style lang="less" scoped>
  :deep(.ant-tree) {
    background: transparent;
  }
</style>
